package vma.nicici.chat;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;

import vma.nicici.chat.api.Api;
import vma.nicici.chat.api.Api.GetRequestParameters;
import vma.nicici.chat.communication.AsynchCallback;
import vma.nicici.chat.gson.Message;
import vma.nicici.chat.history.HistoryDatabase;
import vma.nicici.chat.ui.MessageArrayAdapter;
import vma.nicici.ext.ProgressDialogManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.method.DateTimeKeyListener;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.Request;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.model.GraphUser;

public class LoginActivity extends ListActivity implements OnScrollListener {

	public static final boolean REAL_MODE = false;
	
	public static final String LOGTAG = "LoginActivity";
	
	private static final int INITIAL_MSG_COUNT = 10;
	private static final int LOAD_MORE_COUNT = 1;
	private static final String PREFERENCE_LASTPULL = "lpts";
	private static final String PREFERENCE_LASTPULL_DEFAULT = "-1";
	public static final double NO_COORDINATES = -1d;

	Api api;
	HistoryDatabase history;
	Button postMessageButton;
	ArrayList<Message> messages;
	MessageArrayAdapter listAdapter;
	ProgressDialogManager progressManager;
	String lastPullTimestamp;
	Timer checkMsgTimer;
	
	LocationManager locationManager;
	String providerName;
	
	boolean reachedEndOfHistory = false;
	
	
	
	
	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		hideUpperBar();
		
		
		setContentView(R.layout.activity_login);
		registerForContextMenu(getListView());
		init();
		api = new Api();

		tryToLogin();
		messages = history.getMostRecentMessages(INITIAL_MSG_COUNT);
		listAdapter = new MessageArrayAdapter(this,
				messages,history);
		
		
		setListAdapter(listAdapter);
		getListView().setOnScrollListener(this);
		
		
		progressManager = new ProgressDialogManager(this);
		
		  
        checkForNewMessages();
        checkMsgTimer = new Timer();
        checkMsgTimer.scheduleAtFixedRate(new TimerTask() {
			
			@Override
			public void run() {
				checkForNewMessages();
				
			}
		},0, 3 * 1000);        
	}
	
	private void checkForNewMessages(){
		if (isNetworkAvailable()) {
			api.pullResponseAsynch(api.new GetRequestParameters(lastPullTimestamp), newMessageCallback);
		}
	}
	
	private void hideUpperBar() {
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
	}
	
	private void init() {		
		
		SharedPreferences settings = getPreferences(MODE_PRIVATE);	
		lastPullTimestamp = settings.getString(PREFERENCE_LASTPULL, PREFERENCE_LASTPULL_DEFAULT);
		
		
		
		postMessageButton = (Button) findViewById(R.id.buttonPostMessage);
		postMessageButton.setOnClickListener(onPostMessageButtonClick);
		
		
		
		HistoryDatabase.initialize(this);
		history = HistoryDatabase.getInstance();
		history.open();
		messages = history.getAllMessages();

	}
	
	private void enableLocationSettings() {
	    Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
	    startActivity(settingsIntent);
	}
	
	private View.OnClickListener onPostMessageButtonClick = new  View.OnClickListener() {
		@Override
		public void onClick(View v) {
			setupPostDialog();
		}
	};
	
	
	 private void setupPostDialog() {
	    	LoginActivity.this.runOnUiThread(new Runnable() {
	    	    public void run() {
			    	final EditText input = new EditText(LoginActivity.this);
			    	new AlertDialog.Builder(LoginActivity.this)
			        .setTitle(getString(R.string.postMessageTitle))
			        .setMessage(getString(R.string.postMessageText))
			        .setView(input)
			        .setPositiveButton(getString(R.string.add), new DialogInterface.OnClickListener() {
			            public void onClick(DialogInterface dialog, int whichButton) {
			                Editable value = input.getText(); 
			                if (value.length() <= 0)
			                	return;
			                
			                progressManager.startNew(R.string.working);
			                
			                if (isNetworkAvailable()) {
			                	api.postResponseAsynch(api.new PostRequestParameters(lastPullTimestamp, value.toString(), NO_COORDINATES, NO_COORDINATES), 
				                		newMessageCallback
				                		);
			                } else {
			                	Toast.makeText(LoginActivity.this, "Network error, check your connection!", Toast.LENGTH_LONG).show();
			                	progressManager.stop();
			                }
			                
			            }
			        }).setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
			            public void onClick(DialogInterface dialog, int whichButton) {
			            }
			        }).setNeutralButton(R.string.addWithLocation, new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
							final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
							if (!gpsEnabled) {
								enableLocationSettings();
							}
						     	setupGps();
							    Editable value = input.getText(); 
					            if (value.length() <= 0)
					                	return;
					                
					            progressManager.startNew(R.string.working);
								
							       double lat,lon;
					                lat=lon= NO_COORDINATES;
					                
					                Location gps = getGps();
					                if (gps != null) {
					                	lat = gps.getLatitude();
					                	lon = gps.getLongitude();
					                	Log.d("gps", String.format("lat: %f, lon: %f", lat, lon));
					                }  else {
					                	Log.d("gps", "is null!");
					                }
					                
					                api.postResponseAsynch(api.new PostRequestParameters(lastPullTimestamp, value.toString(), lat, lon), 
					                		newMessageCallback
					                  );
						    
						}
					})
			        
			        .show();
			    	
	    	    }
	    	});
	    }
	 
		AsynchCallback<vma.nicici.chat.gson.Response> newMessageCallback = new AsynchCallback<vma.nicici.chat.gson.Response>() {
			@Override
			public void onFinished(final vma.nicici.chat.gson.Response response) throws IOException,
					URISyntaxException {
	    		   
	    		   LoginActivity.this.runOnUiThread(new Runnable() {
	    			   @Override
	    			   public void run() {
	    				   if(response == null) {
	    					   progressManager.stop(); 
	    					       					   
	    				   } else {
	    					   parseNewMessages(response.messages);
		    				   lastPullTimestamp = response.pullTimestamp;
		            		   progressManager.stop();  
	    				   }	    				    
	    			   }  
	    		     });
			}
		};
		
		
		private boolean isNetworkAvailable() {
		    ConnectivityManager connectivityManager 
		          = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		    return activeNetworkInfo != null;
		}
		
	 
	 private void setupGps() {
		  locationManager =
			        (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		 
		
		 Criteria criteria = new Criteria();
		 criteria.setAccuracy(Criteria.ACCURACY_COARSE);
		 criteria.setAltitudeRequired(false);
		 criteria.setSpeedRequired(false);
		 providerName = locationManager.getBestProvider(criteria, true);
	 }
	 
	 private Location getGps() {
		 if (providerName == null)
			 return null;
		 
		 
		 return locationManager.getLastKnownLocation(providerName);
	 }
	
	
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		Log.d(LOGTAG, "list Item Click, position #" + position);
		if (isNetworkAvailable()) {
			super.onListItemClick(l, v, position, id);
			Intent in = new Intent("android.intent.action.DETAIL");
			in.putExtra("msg", messages.get(position));
			startActivity(in);
		} else {
			Toast.makeText(LoginActivity.this, "Network error, check your connection!", Toast.LENGTH_LONG).show();
		}		
	}

	@Override
	protected void onResume() {
		super.onResume();
		Log.d(LOGTAG, "onResume, Messages size: " + messages.size());
		listAdapter.notifyDataSetChanged();
	}


	public void tryToLogin() {
		Log.d("Facebook", "Trying to login");
		Session.openActiveSession(this, true, new Session.StatusCallback() {
			@Override
			public void call(final Session session, SessionState state,
					Exception exception) {
				Log.d("Facebook", "Call");

				if (session.isOpened()) {
					Log.d("Facebook", "Session is opened");
					Request.executeMeRequestAsync(session,
							new Request.GraphUserCallback() {

								@Override
								public void onCompleted(GraphUser user,
										Response response) {
									Log.d("Facebook", "Request.onCompleted");
									if (user != null) {
										Log.d("Facebook", "User is not null");
										api.setUser(user);
										api.setSession(session);
										TextView loggedInfo = (TextView) findViewById(R.id.loginInfo);
										loggedInfo.setText("Logged in as "
												+ user.getName());										
									}
								}
							});
				}
			}
		});
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		Session.getActiveSession().onActivityResult(this, requestCode,
				resultCode, data);
	}
	
	protected void onPause() {
		super.onPause();
		saveTimestampToPreferences();
	};
	
	private void saveTimestampToPreferences(){
		SharedPreferences settings = getPreferences(MODE_PRIVATE);
		SharedPreferences.Editor editor = settings.edit();
		editor.putString(PREFERENCE_LASTPULL, lastPullTimestamp);
		editor.commit();
	}
	

	@Override
	protected void onDestroy() {
		super.onDestroy();	
		checkMsgTimer.cancel();
		history.close();		
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		if (!reachedEndOfHistory) {
			boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
			if (loadMore && messages != null && messages.size() != 0) {
				Log.d(LOGTAG, "som na konci listu");
				loadMore(messages.get(messages.size() - 1).timestamp);
			}
		}
	}

	private void loadMore(String oldestTimestamp) {
		ArrayList<Message> moreHistory = history.getMessagesBeforeTime(
				oldestTimestamp, LOAD_MORE_COUNT);
		if (moreHistory.size() == 0) {
			reachedEndOfHistory = true;
			return;
		}
		messages.addAll(moreHistory);
		refreshListAdapter();

	}
	
	private void refreshListAdapter(){
		listAdapter.setMessages(messages);
		listAdapter.notifyDataSetChanged();
	}
	
	private synchronized void parseNewMessages(Message[] messagesFromResponse) {
		ArrayList<Message> freshMessages = new ArrayList<Message>(
				Arrays.asList(messagesFromResponse));
		if (REAL_MODE) {
			for (Iterator<Message> it = freshMessages.iterator(); it.hasNext();) {
				Message message = it.next();
				if (message.facebookUserID < 4 || message.lat <= 0
						|| message.lon <= 0) {
					it.remove();
				}
			}
		}
		history.insertMessages(freshMessages);
		freshMessages.addAll(messages);
		messages = freshMessages;
		refreshListAdapter();
	}

}
